use core::{Summary, Package, PackageId};
use sources::{PathSource, GitSource};
+use sources::git;
use util::{Config, CargoResult};
use util::errors::human;
Remote(Url),
}
-#[deriving(Clone, PartialEq, Eq)]
+#[deriving(Clone, Eq)]
pub struct SourceId {
pub kind: SourceKind,
pub location: Location,
}
}
+// This custom implementation handles situations such as when two git sources
+// point at *almost* the same URL, but not quite, even when they actually point
+// to the same repository.
+impl PartialEq for SourceId {
+ fn eq(&self, other: &SourceId) -> bool {
+ if self.kind != other.kind { return false }
+ if self.location == other.location { return true }
+
+ match (&self.kind, &other.kind, &self.location, &other.location) {
+ (&GitKind(..), &GitKind(..),
+ &Remote(ref u1), &Remote(ref u2)) => {
+ git::canonicalize_url(u1.to_str().as_slice()) ==
+ git::canonicalize_url(u2.to_str().as_slice())
+ }
+ _ => false,
+ }
+ }
+}
+
impl SourceId {
pub fn new(kind: SourceKind, location: Location) -> SourceId {
SourceId { kind: kind, location: location }
return Ok(ret);
}
}
+
+#[cfg(test)]
+mod tests {
+ use super::{SourceId, Remote, GitKind};
+
+ #[test]
+ fn github_sources_equal() {
+ let loc = Remote(from_str("https://github.com/foo/bar").unwrap());
+ let s1 = SourceId::new(GitKind("master".to_string()), loc);
+
+ let loc = Remote(from_str("git://github.com/foo/bar").unwrap());
+ let mut s2 = SourceId::new(GitKind("master".to_string()), loc);
+
+ assert_eq!(s1, s2);
+
+ s2.kind = GitKind("foo".to_string());
+ assert!(s1 != s2);
+ }
+}
}
// Some hacks and heuristics for making equivalent URLs hash the same
-fn canonicalize_url(url: &str) -> String {
+pub fn canonicalize_url(url: &str) -> String {
let url = strip_trailing_slash(url);
// HACKHACK: For github URL's specifically just lowercase
let lower_url = url.chars().map(|c|c.to_lowercase()).collect::<String>();
let url = if lower_url.as_slice().contains("github.com") {
- lower_url
+ if lower_url.as_slice().starts_with("https") {
+ lower_url
+ } else {
+ let pos = lower_url.as_slice().find_str("://").unwrap_or(0);
+ "https".to_string() + lower_url.as_slice().slice_from(pos)
+ }
} else {
url.to_string()
};
assert_eq!(ident1, ident2);
}
+ #[test]
+ fn test_canonicalize_idents_different_protocls() {
+ let ident1 = ident(&Remote(url("https://github.com/PistonDevelopers/piston")));
+ let ident2 = ident(&Remote(url("git://github.com/PistonDevelopers/piston")));
+ assert_eq!(ident1, ident2);
+ }
+
fn url(s: &str) -> Url {
url::from_str(s).unwrap()
}